#include <iostream>
#include <string>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <assert.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;

int main(){
    //1. 创建管道
    int pipefd[2]={0};
    int ret = pipe(pipefd);
    assert(ret != -1); //在release模式下，assert语句被删除，ret成了未使用的变量。
    (void)ret; //强转void是为了接触编译警告。

#ifdef DEBUG //条件编译：调试时编译
    cout << "pipefd[0]: " << pipefd[0] << endl;
    cout << "pipefd[1]: " << pipefd[1] << endl;
#endif

    //2.创建子进程
    pid_t id = fork();
    assert(id != -1);
    if(id == 0)
    {
        //子进程是通信接收方
        //3.构建单向通信的信道
        close(pipefd[1]); //关闭写端
        //4.接收信息
        char r_buff[1024];
        size_t cnt = 0;
        while(true)
        {
            //sleep(10);
            ssize_t sz = read(pipefd[0], r_buff, sizeof(r_buff)-1);
            if(sz>0)
            {
                r_buff[sz] = '\0';
                printf("I'm child process! pid:%d ppid:%d\n", getpid(), getppid());
                cout << "father# " << r_buff << endl;  
                // ++cnt;
                // if(cnt == 10) 
                // {
                //     cout << "reader quit(child)!" << endl;
                //     break;
                // }
            }
            else if(sz == 0)
            {
                cout << "writer quit(father), reader quit(child)!" << endl;
                break;
            }
        }
        exit(0);
    }

    //父进程是通信发送方
    //3.构建单向通信的信道
    close(pipefd[0]); //关闭读端
    //4.发送信息
    char w_buff[1024];
    size_t cnt = 0;
    string message = "我是父进程，正在向子进程发送消息！";
    while(true)
    {
        snprintf(w_buff, sizeof(w_buff), "%s pid:%d cnt:%d", message.c_str(), getpid(), ++cnt);
        write(pipefd[1], w_buff, strlen(w_buff)); //注意使用strlen
        // cout << cnt << endl;
        if(cnt == 10)
        {
            cout << "writer quit(father)!" << endl;
            break;
        }
        sleep(1);
    }    
    close(pipefd[1]); //父进程退出前关闭写端
    pid_t cpid = waitpid(id, nullptr, 0);
    assert(ret != -1);
    cout << "child process quit! child_pid: " << cpid << endl;
    return 0;
}